package server;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import server.files.SFileManager;
import util.MD5Checksum;


/**
 * Acts as a single point of entry to server management, and the server side of RMI.
 * Provides public methods for checking files in and out the system.
 * @author ernesta
 */
public class ServerHandler extends UnicastRemoteObject implements ServerInterface {
    private final String REPO_PATH = "";
    private final String TEMP_PATH = "";
    private final String VERSION_PATH = "";
    
    private static ServerHandler server;
    private SFileManager manager;
    
    
    public ServerHandler() throws RemoteException {
        manager = SFileManager.getInstance();
    }
    
    /**
     * Checks if a local file is in conflict with its remote version.
     * @param filename name of a local file
     * @param hash MD5 checksum of the local file
     * @param lastSave UNIX time of the last save of the local file
     * @return 0 for identical files, 1 for different files with no conflict, 2 for conflict
     */
    @Override
    public int checkForConflict(String filename, String hash, long lastSave) {
        String sHash = "";
        
        try {
            sHash = MD5Checksum.getMD5Checksum(filename);
        } catch (FileNotFoundException ex) {
            System.out.println(ex);
        }

        long lastCommit = manager.getCommitTime(filename);
        
        if (sHash.equals(hash)) return 0;
        if (lastSave <= lastCommit) return 1;
        
        //Not sure this is actually possible
        //If it is, not sure this check tackles the problem fully
        return 2;
    }
    
    
    /**
     * A getter for a file's last commit time.
     * @param filename name of a local file
     * @return UNIX time of the last commit of the file, or -1 for an error
     */
    @Override
    public long getCommitTime(String filename) {
        return manager.getCommitTime(filename);
    }
    
    
    /**
     * A getter for a file's lock time.
     * @param filename name of a local file
     * @return UNIX time of the the file's lock, or -1 for an error
     */
    @Override
    public long getLockTime(String filename) {
        return manager.getLockTime(filename);
    }
    
    
    /**
     * A getter for the author of the last commit.
     * @param filename name of the local file
     * @return username of the commit author
     */
    @Override
    public String getAuthor(String filename) {
        return manager.getAuthor(filename);
    }
    
    
    /**
     * A getter for the user who has locked a particular file.
     * @param filename name of the local file
     * @return username of the locking user
     */
    @Override
    public String getLocker(String filename) {
        return manager.getAuthor(filename);
    }
    
    
    /**
     * Carries out the required procedures for full lock of the file on the server.
     * Involves checking current file state, a physical lock and a database edit.
     * @param filename name of the local file
     * @param username name of the user willing to lock the file
     * @return true for success, false for failure
     */
    @Override
    public boolean checkout(String filename, String username) {
        if (!manager.isLocked(filename)) return false;
        if (!manager.lock(filename)) return false;
        if (!manager.lockFileDB(filename, username)) {
            manager.unlock(filename);
            return false;
        }
        
        return true;
    }
    
    
    /**
     * Carries out the required procedures for a complete commit of a file.
     * @param filename name of a local file
     * @param username name of the committing user
     * @return true for success, false for failure
     */
    @Override
    public boolean checkin(String filename, String username) {
        String newFilename = "";
        
        try {
            newFilename = manager.renameWithVersion(filename, REPO_PATH);
            manager.moveFile(newFilename, REPO_PATH, VERSION_PATH);
            manager.moveFile(filename, TEMP_PATH, REPO_PATH);
            manager.unlock(filename);
            
            manager.unlockFileDB(filename, username);
            manager.addVersionDB(filename, username);
        } catch (IOException ex) {
            System.out.println(ex);
        }
        
        return true;
    }
    
    public void testDB(String filename, String username) {
        manager.unlockFileDB(filename, username);
    }
}